package theTVDB
{
	import mx.collections.ArrayCollection;

	import theTVDB.com.control.Controller;
	import theTVDB.com.event.GetDefaultEpisodeEvent;
	import theTVDB.com.event.GetSeriesEvent;
	import theTVDB.com.event.SearchSeriesEvent;
	import theTVDB.com.service.Services;
	import theTVDB.com.vo.EpisodeVO;
	import theTVDB.com.vo.SeriesVO;


	public class TheTVDB
	{
		private static var _instance:TheTVDB ;

		private var controller:Controller = new Controller();
		private var services:Services = Services.getInstance();

		public function TheTVDB(enforcer:SingletonEnforcer)
		{
			if (_instance != null)
				throw new Error( "Only one TheTVDB instance should be instantiated" );

			trace("TheTVDB created");
			services.UpdateMirrors();
		}

		public static function getInstance():TheTVDB
		{
			if (_instance == null)
				_instance = new TheTVDB(new SingletonEnforcer());
			return _instance;
		}

		public function set APIKey(key:String):void
		{
			services.APIKey = key;
		}

		public function get APIKey():String
		{
			return services.APIKey;
		}

		protected var _searchResults:Object = new Object();
		protected var _searchResultsCallbacks:Object = new Object();

		public function searchForSeries(searchString:String, callback:Function):void
		{
			if (_searchResults.hasOwnProperty(searchString))
			{
				callback(_searchResults[searchString]);
				return;
			}

			if (_searchResultsCallbacks.hasOwnProperty(searchString))
			{
				(_searchResultsCallbacks[searchString] as ArrayCollection).addItem(callback);
				return;
			}
			else
			{
				_searchResultsCallbacks[searchString] = new ArrayCollection();
				(_searchResultsCallbacks[searchString] as ArrayCollection).addItem(callback);
			}

			trace("TheTVDB: Searching: " + searchString);

			var event:SearchSeriesEvent = new SearchSeriesEvent();
			event.seriesName = searchString;
			event.callback = searchComplete;
			event.dispatch();
		}

		private function searchComplete(data:ArrayCollection, searchString:String):void
		{
			trace("TheTVDB: Search complete: " + searchString);
			_searchResults[searchString] = data;
			if (_searchResultsCallbacks.hasOwnProperty(searchString))
			{
				for each (var callback:Function in _searchResultsCallbacks[searchString])
				{
					callback(data);
				}
				_searchResultsCallbacks[searchString] = null;
			}
		}

		protected var _showData:Object = new Object();
		protected var _showDataCallbacks:Object = new Object();

		public function getSeriesData(seriesID:String, callback:Function):void
		{
			if (_showData.hasOwnProperty(seriesID))
			{
				callback(_showData[seriesID]);
				return;
			}

			if (_showDataCallbacks.hasOwnProperty(seriesID))
			{
				(_showDataCallbacks[seriesID] as ArrayCollection).addItem(callback);
				return;
			}
			else
			{
				_showDataCallbacks[seriesID] = new ArrayCollection();
				(_showDataCallbacks[seriesID] as ArrayCollection).addItem(callback);
			}


			trace("TheTVDB: Getting Series ID: " + seriesID);
			var event:GetSeriesEvent = new GetSeriesEvent();
			event.SeriesID = seriesID;
			event.callback = showDataReturned;
			event.dispatch();
		}

		private function showDataReturned(data:SeriesVO, seriesID:String):void
		{
			trace("TheTVDB: Series ID Returned: " + seriesID);
			_showData[seriesID] = data;
			if (_showDataCallbacks.hasOwnProperty(seriesID))
			{
				for each (var callback:Function in _showDataCallbacks[seriesID])
				{
					callback(data);
				}
				_showDataCallbacks[seriesID] = null;
			}
		}

		protected var _episodeData:Object = new Object();
		protected var _episodeDataCallbacks:Object = new Object();

		public function getDefaultEpisodeData(seriesID:String, season:int, episode:int, callback:Function):void
		{
			if (_episodeData.hasOwnProperty(seriesID))
			{
				if (_episodeData[seriesID].hasOwnProperty(season))
				{
					if (_episodeData[seriesID][season].hasOwnProperty(episode))
					{
						callback(_episodeData[seriesID][season][episode]);
						return;
					}
				}
			}

			if (_episodeDataCallbacks.hasOwnProperty(seriesID))
			{
				if (_episodeDataCallbacks[seriesID].hasOwnProperty(season))
				{
					if (_episodeDataCallbacks[seriesID][season].hasOwnProperty(episode))
					{
						(_episodeDataCallbacks[seriesID][season][episode] as ArrayCollection).addItem(callback);
						return;
					}
				}
				else
				{
					_episodeDataCallbacks[seriesID][season] = new Object();
				}
			}
			else
			{
				_episodeDataCallbacks[seriesID] = new Object();
				_episodeDataCallbacks[seriesID][season] = new Object();
			}

			_episodeDataCallbacks[seriesID][season][episode] = new ArrayCollection();
			(_episodeDataCallbacks[seriesID][season][episode] as ArrayCollection).addItem(callback);


			trace("TheTVDB: Getting Episode: S" + season.toString() + " E"+ episode.toString() + " for Series" + seriesID);
			var event:GetDefaultEpisodeEvent = new GetDefaultEpisodeEvent();
			event.seriesID = seriesID;
			event.season = season;
			event.episode = episode;
			event.callback = defaultEpisodeDataReturned;
			event.dispatch();
		}

		private function defaultEpisodeDataReturned(data:EpisodeVO, seriesID:String, season:int, episode:int):void
		{
			trace("TheTVDB: Episode Returned: S" + season.toString() + " E"+ episode.toString() + " for Series" + seriesID);

			if (_episodeData.hasOwnProperty(seriesID))
			{
				if (_episodeData[seriesID].hasOwnProperty(season) == false)
				{
					_episodeData[seriesID][season] = new Object();
				}
			}
			else
			{
				_episodeData[seriesID] = new Object();
				_episodeData[seriesID][season] = new Object();
			}
			_episodeData[seriesID][season][episode] = data;

			if (_episodeDataCallbacks.hasOwnProperty(seriesID))
			{
				if (_episodeDataCallbacks[seriesID].hasOwnProperty(season))
				{
					if (_episodeDataCallbacks[seriesID][season].hasOwnProperty(episode))
					{
						for each (var callback:Function in _episodeDataCallbacks[seriesID][season][episode])
						{
							callback(data);
						}
						_episodeDataCallbacks[seriesID][season][episode] = null;
					}
				}
			}
		}

	}
}

class SingletonEnforcer {}
